﻿Friend Class cDirectionAngle

    Private mAngleDegrees As Double

    Private Const Pi As Double = Math.PI
    Private Const HalfPi As Double = Pi / 2
    Private Const TwoPi As Double = Pi * 2
    Private Const DegreesPerRadian As Double = 57.29577951308
    Private Const RadiansPerDegree As Double = 1 / DegreesPerRadian

    Friend Shared Function CreateByDegrees(ByVal Degrees As Double) As cDirectionAngle

        Dim NewAngle As cDirectionAngle

        NewAngle = New cDirectionAngle(Degrees)
        Return NewAngle

    End Function

    Friend Shared Function CreateByRadians(ByVal Radians As Double) As cDirectionAngle

        Dim NewAngle As cDirectionAngle

        NewAngle = New cDirectionAngle(RadiansToDegrees(Radians))
        Return NewAngle

    End Function

    Friend Shared Function CreateByCartesianOffset(ByVal OffsetX As Double, ByVal OffsetY As Double) As cDirectionAngle

        Dim BufferRadians As Double
        Dim Degrees As Double
        Dim NewAngle As cDirectionAngle

        If OffsetX = 0 Then
            If OffsetY > 0 Then
                BufferRadians = HalfPi
            ElseIf OffsetY < 0 Then
                BufferRadians = HalfPi * 3
            Else
                BufferRadians = 0
            End If
        Else
            BufferRadians = Math.Atan(OffsetY / OffsetX)
            If OffsetX < 0 Then
                BufferRadians = BufferRadians + Pi
            End If
        End If

        Degrees = RadiansToDegrees(BufferRadians)

        NewAngle = New cDirectionAngle(Degrees)

        Return NewAngle

    End Function

    Private Sub New(ByVal AngleDegrees As Double)

        mAngleDegrees = AngleDegrees
        ReRangeDegrees()

    End Sub

    Friend Sub ReverseDirection()

        Dim AngleDegrees As Double

        AngleDegrees = mAngleDegrees - 180

        If AngleDegrees < 0 Then
            AngleDegrees = AngleDegrees + 360
        End If

        Me.Degrees = AngleDegrees

    End Sub

    Friend Property Degrees() As Double
        Get
            Return mAngleDegrees
        End Get
        Set(value As Double)
            mAngleDegrees = value
            ReRangeDegrees()
        End Set
    End Property

    Friend Sub AddDegrees(ByVal HowManyToAdd As Double)

        mAngleDegrees += HowManyToAdd
        ReRangeDegrees()

    End Sub

    Friend ReadOnly Property Radians() As Double
        Get
            Return DegreesToRadians(mAngleDegrees)
        End Get
    End Property

    Friend Function Cosine() As Double
        Return Math.Cos(Radians)
    End Function

    Friend Function Sine() As Double
        Return Math.Sin(Radians)
    End Function

    Private Shared Function DegreesToRadians(ByVal Degrees As Double) As Double

        Dim Angle As Double

        Angle = Degrees
        Angle = RadiansPerDegree * Angle
        Angle = HalfPi - Angle

        DegreesToRadians = ReRangeRadians(Angle)

    End Function

    Private Shared Function RadiansToDegrees(ByVal Radians As Double) As Double

        Dim Angle As Double

        Angle = Radians
        Angle = DegreesPerRadian * Angle
        Angle = 90 - Angle

        RadiansToDegrees = Angle

    End Function

    Private Shared Function ReRangeRadians(ByVal Angle As Double) As Double

        Dim WorkingAngle As Double

        WorkingAngle = Angle
        Do While WorkingAngle < 0
            WorkingAngle = WorkingAngle + TwoPi
        Loop
        Do While WorkingAngle > TwoPi
            WorkingAngle = WorkingAngle - TwoPi
        Loop
        ReRangeRadians = WorkingAngle

    End Function

    Private Sub ReRangeDegrees()

        Dim WorkingAngle As Double

        WorkingAngle = mAngleDegrees
        Do While WorkingAngle < 0
            WorkingAngle = WorkingAngle + 360
        Loop
        Do While WorkingAngle > 360
            WorkingAngle = WorkingAngle - 360
        Loop
        If WorkingAngle = 360 Then
            WorkingAngle = 0
        End If
        mAngleDegrees = WorkingAngle

    End Sub

End Class
